// -*- Mode: objc; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-'
//
// This file is part of the cocoa-armory
// Copyright (C) 2007  alfonso e. urdaneta 
//                     alfonso.e.urdaneta@gmail.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#import "ArmoryXmlParser.h"
#import <Cocoa/Cocoa.h>
#import <CoreFoundation/CoreFoundation.h>


@implementation ArmoryXmlParser

- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    NSLog(@"parserDidStartDocument");
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    NSLog(@"parserDidEndDocument");
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI 
 qualifiedName:(NSString *)qualifiedName 
    attributes:(NSDictionary *)attributeDict
{
    NSLog(@"didStartElement");
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"parseError: %s", [parseError localizedFailureReason]);
}

void *createStructure(CFXMLParserRef parser,
                      CFXMLNodeRef node, void *info) 
{
    NSLog(@"createStructure");
    CFStringRef myTypeStr;
    CFStringRef myDataStr;
    CFXMLDocumentInfo *docInfoPtr;

    // Use the dataTypeID to determine what to print.

    switch (CFXMLNodeGetTypeCode(node)) 
    {
    case kCFXMLNodeTypeDocument:
        NSLog(@"kCFXMLNodeTypeDocument");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeDocument\n");
        docInfoPtr = CFXMLNodeGetInfoPtr(node);
        NSLog(@"docInfoPtr created");
        myDataStr = CFStringCreateWithFormat(NULL,
                                             NULL,
                                             CFSTR("Document URL: %@\n"),
                                             CFURLGetString(docInfoPtr->sourceURL));
        NSLog(@"string created");
        break;
        
    case kCFXMLNodeTypeElement:
        NSLog(@"kCFXMLNodeTypeElement");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeElement\n");
            myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                                 CFSTR("Element: %@\n"), CFXMLNodeGetString(node));
            break;
            
    case kCFXMLNodeTypeProcessingInstruction:
        NSLog(@"kCFXMLNodeTypeProcessingInstruction");
        myTypeStr = CFSTR("Data Type ID:kCFXMLNodeTypeProcessingInstruction\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                                 CFSTR("PI: %@\n"), CFXMLNodeGetString(node));
        break;
        
    case kCFXMLNodeTypeComment:
        NSLog(@"kCFXMLNodeTypeComment");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeComment\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("Comment: %@\n"), CFXMLNodeGetString(node));
        break;
        
    case kCFXMLNodeTypeText:
        NSLog(@"kCFXMLNodeTypeText");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeText\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("Text:%@\n"), CFXMLNodeGetString(node));
        break;

    case kCFXMLNodeTypeCDATASection:
        NSLog(@"kCFXMLNodeTypeCDATASection");
        myTypeStr = CFSTR("Data Type ID: kCFXMLDataTypeCDATASection\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("CDATA: %@\n"), CFXMLNodeGetString(node));
        break;
        
    case kCFXMLNodeTypeEntityReference:
        NSLog(@"kCFXMLNodeTypeEntityReference");
        myTypeStr = CFSTR("Data Type ID:kCFXMLNodeTypeEntityReference\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("Entity reference: %@\n"),
                                             CFXMLNodeGetString(node));
        break;
        
    case kCFXMLNodeTypeDocumentType:
        NSLog(@"kCFXMLNodeTypeDocumentType");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeDocumentType\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("DTD: %@\n"), CFXMLNodeGetString(node));
        break;
        
    case kCFXMLNodeTypeWhitespace:
        NSLog(@"kCFXMLNodeTypeWhitespace");
        myTypeStr = CFSTR("Data Type ID: kCFXMLNodeTypeWhitespace\n");
        myDataStr = CFStringCreateWithFormat(NULL, NULL,
                                             CFSTR("Whitespace: %@\n"), CFXMLNodeGetString(node));
        break;
        
    default:
        myTypeStr = CFSTR("Data Type ID: UNKNOWN\n");
        myDataStr = CFSTR("Unknown type.\n");
    }

    // Print the contents.

    NSLog(@"---Create Structure Called--- \n");
    CFShow(myTypeStr);
    CFShow(myDataStr);

    // Return the data string for use by the addChild and
    // endStructure callbacks.
    return myDataStr;

}


void addChild(CFXMLParserRef parser, void *parent, void *child, void *info) 
{
    NSLog(@"---Add Child Called--- \n");
    NSLog(@"Parent being added to: "); CFShow((CFStringRef)parent);
    NSLog(@"Child being added: "); CFShow((CFStringRef)child);
}


void endStructure(CFXMLParserRef parser, void *xmlType, void *info) 
{
    // Leave evidence that we were called.
    NSLog(@"---End Structure Called for \n"); 
    CFShow((CFStringRef)xmlType);
    // Now that the structure and all of its children have been parsed,
    // we can release the string.
    CFRelease(xmlType);
}

CFDataRef resolveEntity(CFXMLParserRef parser, CFStringRef publicID,
                        CFURLRef systemID, void *info) 
{
    NSLog(@"---resolveEntity Called---\n");
    return NULL;
}

Boolean handleError(CFXMLParserRef parser, SInt32 error, void *info) 
{
    NSLog(@"handleError");
    char buf[512], *s;
    // Get the error description string from the Parser.
    CFStringRef description = CFXMLParserCopyErrorDescription(parser);
    s = (char *)CFStringGetCStringPtr(description,
                                      CFStringGetSystemEncoding());

    // If the string pointer is unavailable, do some extra work.
    if (!s) 
        {
            CFStringGetCString(description, buf, 512,
                               CFStringGetSystemEncoding());
        }
    CFRelease(description);

    // Report the exact location of the error.
    NSLog(@"Parse error (%d) %s on line %d, character %d\n",
          (int)error,
          s,
          (int)CFXMLParserGetLineNumber(parser),
          (int)CFXMLParserGetLocation(parser));
    return false;
}


- (void)initializeParser
{
    NSString *location; 
    CFURLRef sourceURL; 

    NSLog(@"ArmoryXmlParser initializeParser");
    location = @"http://armory.worldofwarcraft.com/#arena-ladder.xml?b=Stormstrike&ts=5"; 
    sourceURL = CFURLCreateWithString (NULL,
                                       (CFStringRef)location,
                                       NULL);

    NSLog(@"creating data and properties from resource");
    BOOL result; 
    SInt32 errorCode; 
    CFDataRef xmlData; 
    result = CFURLCreateDataAndPropertiesFromResource (NULL, 
                                                       sourceURL, 
                                                       &xmlData, NULL, NULL,
                                                       &errorCode); 

    NSLog(@"xmlData seeded with data of length %d", CFDataGetLength( xmlData ));

    // First, set up the parser callbacks.
    CFXMLParserCallBacks callbacks = {0, createStructure, addChild, endStructure, resolveEntity, handleError};
    // Create the parser with the option to skip whitespace.
    CFXMLParserRef parser = CFXMLParserCreate(kCFAllocatorDefault, 
                                              xmlData, 
                                              NULL, 
                                              kCFXMLParserSkipWhitespace, 
                                              kCFXMLNodeCurrentVersion, 
                                              &callbacks,
                                              NULL);
    // Invoke the parser.
    if (!CFXMLParserParse(parser)) 
    {
        NSLog(@"parse failed");
    }
}

- (void)directLoadXml
{
    NSString *location; 
    CFURLRef sourceURL; 
    location = @"http://armory.worldofwarcraft.com/#arena-ladder.xml?b=Stormstrike&ts=5"; 
    sourceURL = CFURLCreateWithString (NULL,
                                       (CFStringRef)location,
                                       NULL);

    NSLog(@"creating data and properties from resource");
    BOOL result; 
    SInt32 errorCode; 
    CFDataRef xmlData; 
    result = CFURLCreateDataAndPropertiesFromResource (NULL, 
                                                       sourceURL, 
                                                       &xmlData, NULL, NULL,
                                                       &errorCode); 


    NSLog(@"xmlData length %d", CFDataGetLength( xmlData ));
    CFXMLTreeRef cfXMLTree = CFXMLTreeCreateFromData (kCFAllocatorDefault, 
                                                      xmlData, 
                                                      NULL,
                                                      kCFXMLParserSkipWhitespace, 
                                                      kCFXMLNodeCurrentVersion);
    
    NSLog(@"tree created");
    CFShow(cfXMLTree);
    NSLog(@"tree showed");
}


@end
